package com.ys.web.service.impl;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.charset.Charset;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.omg.PortableServer.ImplicitActivationPolicyOperations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.csvreader.CsvReader;
import com.sun.org.apache.bcel.internal.generic.CPInstruction;
import com.ys.WebConstants;
import com.ys.annotation.YsCsv;
import com.ys.csvtemplate.ImportTemplate;
import com.ys.extend.ImportStateRecord;
import com.ys.extend.utils.ContextHolderUtils;
import com.ys.extend.utils.LogUtil;
import com.ys.extend.utils.TimeUtil;
import com.ys.web.entity.Account;
import com.ys.web.entity.KeyWordMaping;
import com.ys.web.entity.OriginBaidu;
import com.ys.web.entity.Originality;
import com.ys.web.entity.PromotionPlan;
import com.ys.web.entity.PromotionUnit;
import com.ys.web.pojo.OriginalityInfo;
import com.ys.web.remotemodel.RemoteAccountInfo;
import com.ys.web.service.AccountService;
import com.ys.web.service.CompanyService;
import com.ys.web.service.ImportBaiduCSVService;
import com.ys.web.service.KeyWordMapingService;
import com.ys.web.service.OriginBaiduService;
import com.ys.web.service.OriginalityService;
import com.ys.web.service.PromotionPlanService;
import com.ys.web.service.PromotionUnitService;
import com.ys.web.ws.service.ManageCompanyInfoService;

/**
 * 导入百度csv文件-Service-实现类
 * 
 * @author wdj
 *
 */
@Service("importBaiduCSVService")
@Transactional
public class ImportBaiduCSVServiceImpl implements ImportBaiduCSVService {
	@Autowired
	private OriginBaiduService originBaiduService;
	@Autowired
	private PromotionPlanService promotionPlanService;
	@Autowired
	private PromotionUnitService promotionUnitService;
	@Autowired
	private KeyWordMapingService keyWordMapingService;
	@Autowired
	private OriginalityService originalityService;
	
	@Autowired
	private ManageCompanyInfoService manageCompanyInfoService;
	
	@Autowired
	private CompanyService companyService;

	/*** 跳过的行 */
	private static final int CSV_IGNORE_ROW = 3;
	/*** 时间范围_列 */
	private static final int CSV_Date_Column = 0;
	/*** 推广计划_列 */
	private static final int CSV_PromotionPlan_Column = 1;
	/*** 推广单元_列 */
	private static final int CSV_PromotionUnit_Column = 2;
	/*** 推广关键词_列 */
	private static final int CSV_PromotionKeyword_Column = 3;
	/*** 搜索关键词_列 */
	private static final int CSV_KeywordSearch_Column = 4;
	/*** 当前单元的添加状态_列 */
	private static final int CSV_AddState_Column = 5;
	/*** 展现量_列 */
	private static final int CSV_NumberExhibit_Column = 6;
	/*** 点击量_列 */
	private static final int CSV_NumberClick_Column = 7;
	/*** 消费_列 */
	private static final int CSV_Consume_Column = 8;
	/*** 点击率_列 */
	private static final int CSV_ClickRate_Column = 9;
	/*** 总转化量_列 */
	private static final int CSV_TotalnumberConsult_Column = 10;
	/*** 精确匹配扩展(地域词扩展)触发_列 */
	private static final int CSV_ExactMatch_Column = 11;
	/*** 高级精确匹配触发_列 */
	private static final int CSV_HightExactMatch_Column = 12;

	@Override
	public Boolean readBaiduCSVToDB(String filePath, Charset charset, Integer userId, Integer companyId,
			Integer accountId) {
		String msg = "开始导入数据库"; // 初始状态
		/** 会话的username */
		String username = (String) ContextHolderUtils.getSession().getAttribute("username");
		// 初始状态
		ImportStateRecord.addStateMsg(username, msg);

		// 百度消费数据列表
		List<OriginBaidu> list = new ArrayList<>();
		// 推广计划
		Set<String> setPlan = new HashSet<String>();
		List<PromotionPlan> listPlan = new ArrayList<>();
		// 推广单元
		Set<String> setUnit = new HashSet<String>();
		List<PromotionUnit> listUnit = new ArrayList<>();
		// 关键词_搜索词
		List<KeyWordMaping> listKeyWordMaping = new ArrayList<>();
		// 关键词_搜索词
		Map<String, Object> mapKWM = new HashMap<>();

		try {
			CsvReader reader = new CsvReader(filePath, ',', charset);
			// 跳过不需要的行
			for (int i = 0; i <= CSV_IGNORE_ROW; i++) {
				reader.readRecord();
			}
			// 判断时间单位是否为“分日”的数据
			if (!"2. 时间单位：分日".equals(reader.get(0))) {
				msg = "导入失败，请导入时间单位为“分日”的数据";
				ImportStateRecord.updateStateMsg(username, msg);
				return false;
			}
			for (int i = 0; i <= CSV_IGNORE_ROW; i++) {
				reader.readRecord();
			}

			// 遍历读取需要的百度数据
			while (reader.readRecord()) {
				// 读取一行记录的全部列,并封装入OriginBaidu实例
				OriginBaidu originBaidu = setOriginBaiduValue(userId, companyId, accountId, reader);
				// 计算“消费转化比”
				double consumeConsultRate = 0;
				double totalnumberConsult = Double.parseDouble(reader.get(CSV_TotalnumberConsult_Column));
				double consume = Double.parseDouble(reader.get(CSV_Consume_Column));
				if (consume != 0) {
					DecimalFormat df = new DecimalFormat("#.000");// 保留3位小数
					consumeConsultRate = Double.parseDouble(df.format(totalnumberConsult / consume));
				}
				originBaidu.setConsumeConsultRate(consumeConsultRate);
				/**
				 * 判断数据库中是否已存在百度数据 若数据库已存在记录，则不新增，直接更新相应记录。
				 */
				OriginBaidu ifExistOriginBaidu = originBaiduService.ifExistOriginBaidu(companyId,
						originBaidu.getPromotionDate(), originBaidu.getPromotionPlan(),
						originBaidu.getPromotionKeyword(), originBaidu.getKeywordSearch());
				if (ifExistOriginBaidu == null) {
					list.add(originBaidu);

					// 推广计划名称,去重复
					setPlan.add(reader.get(CSV_PromotionPlan_Column));

					// 推广单元名称,去重复
					setUnit.add(reader.get(CSV_PromotionUnit_Column));
					// setUnit.add(reader.get(CSV_AddState_Column));//当前单元的添加状态

					// 推广关键词--搜索关键词,去重复和一对多关联
					String csv_promotionKeyword = reader.get(CSV_PromotionKeyword_Column);
					String csv_keywordSearch = reader.get(CSV_KeywordSearch_Column);
					if (!mapKWM.containsKey(csv_promotionKeyword)) {
						StringBuilder sb = new StringBuilder();
						mapKWM.put(csv_promotionKeyword, sb.append(csv_keywordSearch).append(","));
					} else {
						// 拿出相同key的旧value
						StringBuilder sb = (StringBuilder) mapKWM.get(csv_promotionKeyword);
						// 追加相同key的新value
						mapKWM.put(csv_promotionKeyword, sb.append(csv_keywordSearch).append(","));
					}
				} else {
					ifExistOriginBaidu.setImportDate(TimeUtil.getNowTime());
					originBaiduService.update(ifExistOriginBaidu);
				}
			}
			reader.close();

			if (list.size() > 0) {
				// 判断数据库中不存在，再放进List中
				putListPlan(setPlan, companyId, accountId, listPlan);
				putListUnit(setUnit, listUnit);
				putListKeyWordMaping(mapKWM, companyId, listKeyWordMaping);
				// 批量新增
				originBaiduService.batchSave(list);
				promotionPlanService.batchSave(listPlan);
				promotionUnitService.batchSave(listUnit);
				keyWordMapingService.batchSave(listKeyWordMaping);

				// 修改导入状态
				for (int i = 0; i < list.size(); i++) {
					msg = "导入" + i + "条记录";
					if (i == 500) {
						ImportStateRecord.updateStateMsg(username, msg);
					}

					if (i == 1000) {
						ImportStateRecord.updateStateMsg(username, msg);
					}

					if (i == list.size()) {
						ImportStateRecord.updateStateMsg(username, msg);
					}
				}
				msg = "导入成功";
				ImportStateRecord.updateStateMsg(username, msg);
			} else {
				msg = "导入成功，已更新存在的数据";
				ImportStateRecord.updateStateMsg(username, msg);
			}
		} catch (Exception e) {
			e.printStackTrace();
			msg = "导入失败，文件格式异常";
			ImportStateRecord.updateStateMsg(username, msg);
			return false;
		}

		return true;
	}

	/**
	 * set入实例
	 * 
	 * @param userId
	 * @param companyId
	 * @param accountId
	 * @param reader
	 * @return 实例
	 * @throws IOException
	 */
	private static OriginBaidu setOriginBaiduValue(Integer userId, Integer companyId, Integer accountId,
			CsvReader reader) throws IOException {
		int i = 0;// 初始下标
		OriginBaidu originBaidu = new OriginBaidu();
		originBaidu.setImportDate(TimeUtil.getNowTime());
		originBaidu.setUserId(userId);
		originBaidu.setCompanyId(companyId);
		originBaidu.setAccountId(accountId);
		originBaidu.setPromotionDate(TimeUtil.getFormatDate(reader.get(i++), "yyyy-MM-dd"));
		originBaidu.setPromotionPlan(reader.get(i++));
		originBaidu.setPromotionUnit(reader.get(i++));
		originBaidu.setPromotionKeyword(reader.get(i++));
		originBaidu.setKeywordSearch(reader.get(i++));
		originBaidu.setAddState(reader.get(i++));
		originBaidu.setNumberExhibit(Integer.parseInt(reader.get(i++)));
		originBaidu.setNumberClick(Integer.parseInt(reader.get(i++)));
		originBaidu.setConsume(Double.parseDouble(reader.get(i++)));
		originBaidu.setClickRate(reader.get(i++));
		originBaidu.setTotalnumberConsult(Integer.parseInt(reader.get(i++)));
		originBaidu.setExactMatch(reader.get(i++));
		originBaidu.setHightExactMatch(reader.get(i++));
		return originBaidu;
	}

	/**
	 * 放进ListPlan
	 * 
	 * @param setPlan
	 * @param companyId
	 * @param accountId
	 * @param listPlan
	 */
	private void putListPlan(Set<String> setPlan, Integer companyId, Integer accountId, List<PromotionPlan> listPlan) {
		Iterator itePlan = setPlan.iterator();
		while (itePlan.hasNext()) {
			PromotionPlan promotionPlan = new PromotionPlan();
			promotionPlan.setCompanyId(companyId);
			promotionPlan.setAccountId(accountId);
			promotionPlan.setPlanName(itePlan.next().toString());
			// 判断数据库中是否存在此“推广计划”
			Boolean ifExist = promotionPlanService.ifExistPromotionPlan(companyId, promotionPlan.getPlanName());
			if (!ifExist) {
				listPlan.add(promotionPlan);
			}
		}
	}

	/**
	 * 放进ListUnit
	 * 
	 * @param setUnit
	 * @param listUnit
	 */
	private void putListUnit(Set<String> setUnit, List<PromotionUnit> listUnit) {
		Iterator iteUnit = setUnit.iterator();
		while (iteUnit.hasNext()) {
			PromotionUnit promotionUnit = new PromotionUnit();
			promotionUnit.setUnitName(iteUnit.next().toString());
			// 判断数据库中是否存在此“推广单元”
			Boolean ifExist = promotionUnitService.ifExistPromotionUnit(promotionUnit.getUnitName());
			if (!ifExist) {
				listUnit.add(promotionUnit);
			}
		}
	}

	/**
	 * 放进ListKeyWordMaping
	 * 
	 * @param mapKWM
	 * @param companyId
	 * @param listKeyWordMaping
	 */
	private void putListKeyWordMaping(Map<String, Object> mapKWM, Integer companyId,
			List<KeyWordMaping> listKeyWordMaping) {
		for (Map.Entry<String, Object> entry : mapKWM.entrySet()) {
			KeyWordMaping keyWordMaping = new KeyWordMaping();
			keyWordMaping.setCompanyId(companyId);
			keyWordMaping.setPromotionKeyword(entry.getKey());
			keyWordMaping.setKeywordSearch(entry.getValue().toString());
			// 判断数据库中是否存在“推广关键词对应多个搜索关键词”
			Boolean ifExist = keyWordMapingService.ifExistKeyWordMaping(keyWordMaping.getPromotionKeyword());
			if (!ifExist) {
				listKeyWordMaping.add(keyWordMaping);
			}
		}
	}

	@Override
	public Integer readBaiduOriginalityToDB(String filePath, Charset charset,Integer userId) {
		// TODO Auto-generated method stub
		String msg = "开始导入数据库"; // 初始状态

		List<Originality> originalities = new ArrayList<Originality>();
		/** 会话的username */
		String username = (String) ContextHolderUtils.getSession().getAttribute("username");

		// 初始状态
		ImportStateRecord.addStateMsg(username, msg);

		try {
			CsvReader reader = new CsvReader(filePath, ',', charset);

			List<String[]> dataList = new ArrayList<String[]>();
			// 开始读取csv文件
			int propertySize = ImportTemplate.orginalityProperties.size();
			boolean isstart = false;
			Map<String, Integer> columnIndexMap = new HashMap<String, Integer>();
			while (reader.readRecord()) {
				
				if (isstart) {
					dataList.add(reader.getValues());
				}
				// 如果行里包括3个以上模板字段就判定该行为数据超始行
			
//				System.out.println("test:" + ImportTemplate.orginalityProperties.contains(reader.get(0)));
//				System.out.println("test2:" + ImportTemplate.orginalityProperties.contains(reader.get(1)));
//				System.out.println("test3:" + ImportTemplate.orginalityProperties.contains(reader.get(2)));
				if (ImportTemplate.orginalityProperties.contains(reader.get(0))
						&& ImportTemplate.orginalityProperties.contains(reader.get(1))
						&& ImportTemplate.orginalityProperties.contains(reader.get(2))) {
					
					// 开始读取数据了！！！ 设定为可读取
					isstart = true;
					// 记录模板字段所在列
					
					for (int i = 0; i < reader.getValues().length; i++) {
						// 添加模板字段，并保存其所在列
						if (ImportTemplate.orginalityProperties.contains(reader.getValues()[i])) {
							columnIndexMap.put(reader.getValues()[i], i);
							propertySize--;
						}

					}

					if (propertySize > 0) {
						LogUtil.info("缺少字段");
						msg = "缺少字段";
						ImportStateRecord.updateStateMsg(username, msg);
					}
					
					
				}

				
			}

			reader.close();// 关闭流
			// 开始数据对象化

			dataList.stream().forEach(c -> {
				try {
					// 利用注解把数据反射到对象里
					Originality originality = (Originality) Class.forName(Originality.class.getName())
							.newInstance();
					for (Field field : originality.getClass().getDeclaredFields()) {
						
						YsCsv ysCsv = field.getAnnotation(YsCsv.class);
						if (ysCsv != null) {
							int index = columnIndexMap.get(ysCsv.column());// 根据字段的节点
							
							// 判断日期转换
							field.setAccessible(true);
//							System.out.println("isdate:"+(field.get(originalityInfo) instanceof Date));
							if (field.getType() == Date.class) {
								SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
								SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");
								Date dateobj = null;
								if(c[index].trim().indexOf("-")!=-1){
									dateobj=sdf2.parse(c[index].trim());
								}else{
									dateobj=sdf.parse(c[index].trim());
								}
								
								
								field.set(originality, dateobj);
								// 判断数字
							} else if (field.getType() == Double.class) {
								Double d = 0D;
								if(c[index].trim().equals("-")){
									d= -1D;
								}else{
									String doubleStr = c[index].trim();
									if(c[index].trim().indexOf("%")!=-1){
										 doubleStr = doubleStr.replace("%", "");
									}
									d = Double.valueOf(doubleStr);
								}
								
								field.set(originality, d);
							} else if (field.getType() == Integer.class) {
								Integer i = Integer.valueOf(c[index].trim());
								field.set(originality, i);
							} else {
								// string 类型
								field.set(originality, c[index].trim());
							}
						}

					}
					List<RemoteAccountInfo> accounts = manageCompanyInfoService.findBaiduAccountByAccountName(originality.getAccount());
					if(accounts==null||accounts.size()==0){
						LogUtil.info("账户不存在");
						ImportStateRecord.updateStateMsg(username, "导入失败，账户不存在");
						return;
					}else{
						RemoteAccountInfo account = accounts.get(0);
						originality.setAccountId(account.getId());
						originality.setCompanyId(account.getCompanyId());
						originality.setUserId(userId);
						originality.setImportDate(new Date());
						originalities.add(originality);
						
						originalityService.saveOrUpdate(originality);
					}
					
					
				} catch (Exception e) {
					// TODO Auto-generated catch block
					
					ImportStateRecord.updateStateMsg(username, "导入失败");
					e.printStackTrace();
					return;
					
				}

			});
			
			if(originalities.size()<dataList.size()){
				ImportStateRecord.updateStateMsg(username, "导入失败");
				return Integer.valueOf(WebConstants.FAIL_CODE);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			ImportStateRecord.updateStateMsg(username, "导入失败");
			e.printStackTrace();
			return Integer.valueOf(WebConstants.FAIL_CODE);
		}
		ImportStateRecord.updateStateMsg(username, "导入成功");
		return Integer.valueOf(WebConstants.SUCCESS_CODE);
	}

}
